using FanaticDownBlock.Track;
using Godot;
using System;
using System.Collections.Generic;

[Tool]
public partial class BlockGenerator : Node2D
{
    #region props

    public double Speed = 1;

    #endregion

    #region fields

    private Node _parent;
    private TrackInfoList _trackInfoList;

    private int _currentIndex = 0;
    private double _timer = 0;
    private double _lastClearTimer = 0;
    private bool _isActive = false;

    private List<TrackBlock> _trackBlocks = new List<TrackBlock>();

    #endregion


    // Called when the node enters the scene tree for the first time.
    public override void _Ready()
    {
        _trackInfoList = TrackInfoHelper.CreateRandom();
        Reset();
    }

    public override void _EnterTree()
    {
        base._EnterTree();
        _parent = GetParent();
    }

    public override void _ExitTree()
    {
        base._ExitTree();
        _parent = null;
    }

    // Called every frame. 'delta' is the elapsed time since the previous frame.
    public override void _Process(double delta)
    {
        if (_isActive == false) return;
        _timer += delta;



        while (_ProcessNextBlock()) ;

        foreach (var trackBlock in _trackBlocks)
        {
            var distance = Speed * GlobalData.UnitMetric * (_timer - trackBlock.StartTimeSecond);
            trackBlock.Position = new Vector2(trackBlock.Position.X, (float)distance);
        }

        Clear();
    }

    private void Clear()
    {
        if (_timer < _lastClearTimer + 10) return;
        _lastClearTimer = _timer;

        var viewPort = GetViewportRect();
        var removedBlocks = new List<TrackBlock>();
        foreach (var trackBlock in _trackBlocks)
        {
            if (trackBlock.GlobalPosition.Y >= viewPort.Size.Y + 100)
                removedBlocks.Add(trackBlock);
        }

        foreach (var trackBlock in removedBlocks)
        {
            RemoveTrackBlock(trackBlock);
        }
    }

    public void RemoveTrackBlock(TrackBlock trackBlock)
    {
        _trackBlocks.Remove(trackBlock);
        RemoveChild(trackBlock);
        trackBlock.QueueFree();
    }

    private bool _ProcessNextBlock()
    {
        if (_currentIndex >= _trackInfoList.Count || _currentIndex < 0)
        {
            GD.Print($"BlockGenerator._Process: _currentIndex {_currentIndex} _trackInfoList {_trackInfoList.Count}, then stop");
            Stop();
            return false;
        }

        var currentNode = _trackInfoList[_currentIndex];

        // 当触发了当前播放时间，就将当前节点创建。
        if (_timer >= currentNode.StartTimeSecond)
        {
            var newTrackBlock = CreateTrackInfoNode(currentNode);
            _trackBlocks.Add(newTrackBlock);
            AddChild(newTrackBlock);
            _currentIndex++;

            return true;
            //GD.Print($"111");

        }
        else
        {
            return false;
            //GD.Print($"BlockGenerator._Process: {_timer} {currentNode.StartTimeSecond}");
        }
    }

    public void Reset()
    {
        _currentIndex = 0;
        _timer = 0;
        _isActive = false;
        _trackBlocks.Clear();
    }

    public void Play()
    {
        _isActive = true;
    }

    public void Stop()
    {
        _isActive = false;
    }

    ///<summary>创建轨道信息节点。</summary>
    private TrackBlock CreateTrackInfoNode(TrackInfo trackInfo)
    {
        var trackBlock = TrackBlockPackedScene.Instantiate<TrackBlock>();
        trackBlock.DurationSecond = trackInfo.DurationSecond;
        trackBlock.Position = new Vector2(trackInfo.TrackId * 100, 0);
        trackBlock.StartTimeSecond = trackInfo.StartTimeSecond;
        trackBlock.TrackId = trackInfo.TrackId;
        return trackBlock;
    }

    private static Lazy<PackedScene> _trackBlockPackedScene = new Lazy<PackedScene>(() =>
    {
        return GD.Load<PackedScene>(@"res://Prefabs/Blocks/TrackBlock.tscn");
    });
    private static PackedScene TrackBlockPackedScene => _trackBlockPackedScene.Value;

}
